上节我们讲到自定义的方式设置开机动画,系统默认只能使用图片轮播的方式来设置开机动画,表现力有限。如果开机能播放视频,那开机动画会更为炫酷,同时还能满足开机播放广告的“变态需求”。接下来我们就来实操一下。
修改 frameworks/base/cmds/bootanimation/BootAnimation.h
文件:
// 添加头文件
#include <media/mediaplayer.h>
#include <media/IMediaHTTPService.h>
class BootAnimation : public Thread, public IBinder::DeathRecipient
{
//......
bool android();
bool movie();
// BootAnimation 类添加成员函数,video 函数用于播放视频
bool video();
//.....
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
修改 frameworks/base/cmds/bootanimation/BootAnimation.cpp
文件,实现 video 函数:
const char *videoPath = "/system/media/bootvideo.mp4";
bool BootAnimation::video() {
const float MAX_FPS = 60.0f;
const float CHECK_DELAY = ns2us(s2ns(1) / MAX_FPS);
// 屏幕显示初始化
eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
eglDestroySurface(mDisplay, mSurface);
// 播放视频
sp<MediaPlayer> mp = new MediaPlayer();
mp->reset();
mp->setDataSource(NULL, videoPath, NULL);
mp->setVideoSurfaceTexture(mFlingerSurface->getIGraphicBufferProducer());
mp->prepare();
mp->start();
//设置音量
mp->setVolume(1.0, 1.0);
//等Launcher启动完成
while(true) {
if(exitPending()) {
break;
}
usleep(CHECK_DELAY);
checkExit();
}
//等开机视频播放完成
while (mp->isPlaying()) {
usleep(200000);
}
ALOGD("bootvideo play finish");
mp->stop();
mp->disconnect();
mp.clear();
return true;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
实现也很简单,就是使用系统服务 MediaPlayer 播放视频。
接着修改播放动画部分的代码 frameworks/base/cmds/bootanimation/BootAnimation.cpp
bool BootAnimation::threadLoop()
{
bool r;
// We have no bootanimation file, so we use the stock android logo
// animation.
// 播放视频
r = video();
// 注释掉播放动画的代码
// if (mZipFileName.isEmpty()) {
// r = android();
// } else {
// r = movie();
// }
eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
eglDestroyContext(mDisplay, mContext);
eglDestroySurface(mDisplay, mSurface);
mFlingerSurface.clear();
mFlingerSurfaceControl.clear();
eglTerminate(mDisplay);
eglReleaseThread();
IPCThreadState::self()->stopProcess();
return r;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
接着修改 Android.bp 添加 media 库依赖:
// frameworks/base/cmds/bootanimation/Android.bp
cc_defaults {
name: "bootanimation_defaults",
cflags: [
"-DGL_GLEXT_PROTOTYPES",
"-DEGL_EGLEXT_PROTOTYPES",
"-Wall",
"-Werror",
"-Wunused",
"-Wunreachable-code",
],
shared_libs: [
"libandroidfw",
"libbase",
"libbinder",
"libcutils",
"liblog",
"libutils",
// 添加 media 依赖库
"libmedia"
],
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
最后修改 selinux 配置文件
先修改 system/sepolicy/prebuilts/api/29.0/public/
目录下的 bootanim.te
和 mediaserver.te
:
# bootanim.te
binder_call(bootanim, surfaceflinger)
# 添加 bootanim 对 mediaserver 的访问权限
binder_call(bootanim, mediaserver)
binder_call(bootanim, audioserver)
# ......
allow bootanim audioserver_service:service_manager find;
allow bootanim surfaceflinger_service:service_manager find;
# 使得 bootanim 可以从 service_manager 获取到 mediaserver 服务
allow bootanim mediaserver_service:service_manager find;
# mediaserver.te
binder_use(mediaserver)
binder_call(mediaserver, binderservicedomain)
binder_call(mediaserver, appdomain)
# mediaserver 可以通过 binder 访问 bootanim
binder_call(mediaserver, bootanim)
binder_service(mediaserver)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
接着修改 system/sepolicy/public
目录下的 bootanim.te
和 mediaserver.te
:
# bootanim.te
binder_call(bootanim, surfaceflinger)
# 添加 bootanim 对 mediaserver 的访问权限
binder_call(bootanim, mediaserver)
binder_call(bootanim, audioserver)
# ......
allow bootanim audioserver_service:service_manager find;
allow bootanim surfaceflinger_service:service_manager find;
# 使得 bootanim 可以从 service_manager 获取到 mediaserver 服务
allow bootanim mediaserver_service:service_manager find;
# mediaserver.te
binder_use(mediaserver)
binder_call(mediaserver, binderservicedomain)
binder_call(mediaserver, appdomain)
# mediaserver 可以通过 binder 访问 bootanim
binder_call(mediaserver, bootanim)
binder_service(mediaserver)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
接着将 MP4 文件预制到 /system/media/bootvideo.mp4
目录下,文件预制可以参考上一节预制 bootanimation.zip 文件的方法
重新编译系统,启动虚拟机就可以看到自定义的开机界面了:
source build/envsetup.sh
lunch rice14-eng
m
emulator
1
2
3
4
2
3
4